package FutureAndPromise;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * Demo01 - JDK Future 基础使用
 * 
 * 学习目标：
 * 1. 理解 JDK Future 的基本概念
 * 2. 掌握 Future 的核心方法
 * 3. 了解 Future 的局限性
 * 4. 学习如何正确使用 Future
 */
@Slf4j
public class Demo01_JDKFuture {

    public static void main(String[] args) throws Exception {
        log.info("=== JDK Future 基础使用 ===\n");
        
        // 演示 1：Future 基本使用
        demo1_BasicUsage();
        
        // 演示 2：get() 方法详解
        demo2_GetMethod();
        
        // 演示 3：isDone() 和轮询
        demo3_IsDoneAndPolling();
        
        // 演示 4：cancel() 取消任务
        demo4_CancelTask();
        
        // 演示 5：Future 的局限性
        demo5_Limitations();
    }

    /**
     * 演示 1：Future 基本使用
     * 
     * Future 代表一个异步计算的结果
     */
    private static void demo1_BasicUsage() throws Exception {
        log.info("\n┌─────────────────────────────────────────");
        log.info("│ Demo 1: Future 基本使用");
        log.info("└─────────────────────────────────────────\n");
        
        // 创建线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        
        log.info("1. 提交异步任务");
        
        // 提交一个 Callable 任务，返回 Future
        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("   [异步线程] 开始执行任务...");
                Thread.sleep(2000);  // 模拟耗时操作
                log.info("   [异步线程] 任务执行完成");
                return "Hello, Future!";
            }
        });
        
        log.info("2. 主线程继续执行其他任务");
        log.info("   [主线程] 做一些其他工作...");
        Thread.sleep(500);
        
        log.info("3. 获取异步任务的结果");
        String result = future.get();  // 阻塞等待结果
        log.info("   [主线程] 获得结果: {}", result);
        
        executor.shutdown();
    }

    /**
     * 演示 2：get() 方法详解
     * 
     * get() 会阻塞线程，直到任务完成
     */
    private static void demo2_GetMethod() throws Exception {
        log.info("\n┌─────────────────────────────────────────");
        log.info("│ Demo 2: get() 方法详解");
        log.info("└─────────────────────────────────────────\n");
        
        ExecutorService executor = Executors.newCachedThreadPool();
        
        // 情况 1：get() 阻塞等待
        log.info("情况 1：get() 阻塞等待");
        Future<String> future1 = executor.submit(() -> {
            Thread.sleep(1000);
            return "Result 1";
        });
        
        log.info("   调用 get() 前，主线程在运行");
        long start = System.currentTimeMillis();
        String result1 = future1.get();  // 阻塞 1 秒
        long end = System.currentTimeMillis();
        log.info("   get() 返回: {}, 耗时: {} ms", result1, end - start);
        
        // 情况 2：get(timeout) 带超时
        log.info("\n情况 2：get(timeout) 带超时");
        Future<String> future2 = executor.submit(() -> {
            Thread.sleep(3000);  // 睡眠 3 秒
            return "Result 2";
        });
        
        try {
            log.info("   等待最多 1 秒...");
            String result2 = future2.get(1, TimeUnit.SECONDS);  // 最多等 1 秒
            log.info("   get() 返回: {}", result2);
        } catch (TimeoutException e) {
            log.error("   ❌ 超时！任务未在 1 秒内完成");
        }
        
        // 情况 3：任务抛出异常
        log.info("\n情况 3：任务抛出异常");
        Future<String> future3 = executor.submit(() -> {
            Thread.sleep(500);
            throw new RuntimeException("任务执行失败");
        });
        
        try {
            String result3 = future3.get();
            log.info("   结果: {}", result3);
        } catch (ExecutionException e) {
            log.error("   ❌ 任务执行失败: {}", e.getCause().getMessage());
        }
        
        executor.shutdown();
    }

    /**
     * 演示 3：isDone() 和轮询
     * 
     * 使用 isDone() 检查任务是否完成，避免阻塞
     */
    private static void demo3_IsDoneAndPolling() throws Exception {
        log.info("\n┌─────────────────────────────────────────");
        log.info("│ Demo 3: isDone() 和轮询");
        log.info("└─────────────────────────────────────────\n");
        
        ExecutorService executor = Executors.newCachedThreadPool();
        
        Future<String> future = executor.submit(() -> {
            log.info("   [异步任务] 开始执行...");
            Thread.sleep(3000);
            log.info("   [异步任务] 执行完成");
            return "Task completed";
        });
        
        log.info("使用轮询方式等待任务完成：");
        
        // 轮询检查
        int count = 0;
        while (!future.isDone()) {
            count++;
            log.info("   [轮询 {}] 任务还未完成，继续等待...", count);
            Thread.sleep(500);  // 每 500ms 检查一次
        }
        
        log.info("   ✅ 任务已完成！");
        String result = future.get();  // 不会阻塞，因为已经完成
        log.info("   结果: {}", result);
        
        log.info("\n❌ 缺点：轮询浪费 CPU 资源，不够优雅");
        
        executor.shutdown();
    }

    /**
     * 演示 4：cancel() 取消任务
     * 
     * 使用 cancel() 可以尝试取消任务
     */
    private static void demo4_CancelTask() throws Exception {
        log.info("\n┌─────────────────────────────────────────");
        log.info("│ Demo 4: cancel() 取消任务");
        log.info("└─────────────────────────────────────────\n");
        
        ExecutorService executor = Executors.newCachedThreadPool();
        
        // 情况 1：取消未开始的任务
        log.info("情况 1：取消未开始的任务");
        Future<String> future1 = executor.submit(() -> {
            log.info("   [任务 1] 不应该看到这条日志");
            return "Result 1";
        });
        
        boolean cancelled1 = future1.cancel(true);
        log.info("   取消成功: {}", cancelled1);
        log.info("   任务是否取消: {}", future1.isCancelled());
        log.info("   任务是否完成: {}", future1.isDone());
        
        // 情况 2：取消正在执行的任务
        log.info("\n情况 2：取消正在执行的任务");
        Future<String> future2 = executor.submit(() -> {
            log.info("   [任务 2] 开始执行");
            try {
                for (int i = 0; i < 10; i++) {
                    if (Thread.currentThread().isInterrupted()) {
                        log.info("   [任务 2] 检测到中断，退出");
                        return null;
                    }
                    Thread.sleep(500);
                    log.info("   [任务 2] 执行中... {}/10", i + 1);
                }
                return "Completed";
            } catch (InterruptedException e) {
                log.info("   [任务 2] 被中断");
                return null;
            }
        });
        
        Thread.sleep(1500);  // 让任务执行一会儿
        
        log.info("   尝试取消任务...");
        boolean cancelled2 = future2.cancel(true);  // true 表示中断线程
        log.info("   取消成功: {}", cancelled2);
        
        Thread.sleep(1000);
        
        // 情况 3：取消已完成的任务
        log.info("\n情况 3：取消已完成的任务");
        Future<String> future3 = executor.submit(() -> {
            Thread.sleep(100);
            return "Quick task";
        });
        
        Thread.sleep(200);  // 等待任务完成
        
        boolean cancelled3 = future3.cancel(true);
        log.info("   取消成功: {}", cancelled3);  // false，因为已经完成
        log.info("   任务是否完成: {}", future3.isDone());
        
        executor.shutdown();
    }

    /**
     * 演示 5：Future 的局限性
     * 
     * JDK Future 存在很多局限性，这也是为什么需要 CompletableFuture 和 Netty Future
     */
    private static void demo5_Limitations() throws Exception {
        log.info("\n┌─────────────────────────────────────────");
        log.info("│ Demo 5: Future 的局限性");
        log.info("└─────────────────────────────────────────\n");
        
        ExecutorService executor = Executors.newCachedThreadPool();
        
        // 局限 1：无法添加回调
        log.info("局限 1：无法添加回调");
        Future<String> future1 = executor.submit(() -> {
            Thread.sleep(1000);
            return "Result";
        });
        
        log.info("   ❌ 无法在任务完成时自动回调");
        log.info("   只能：");
        log.info("   - 使用 get() 阻塞等待（阻塞线程）");
        log.info("   - 使用 isDone() 轮询（浪费 CPU）");
        
        // 局限 2：无法组合多个 Future
        log.info("\n局限 2：无法组合多个 Future");
        Future<String> futureA = executor.submit(() -> {
            Thread.sleep(1000);
            return "A";
        });
        
        Future<String> futureB = executor.submit(() -> {
            Thread.sleep(1000);
            return "B";
        });
        
        log.info("   ❌ 无法优雅地组合两个 Future 的结果");
        log.info("   必须分别调用 get()：");
        String a = futureA.get();
        String b = futureB.get();
        String result = a + b;
        log.info("   结果: {}", result);
        
        // 局限 3：异常处理不方便
        log.info("\n局限 3：异常处理不方便");
        Future<String> future3 = executor.submit(() -> {
            Thread.sleep(500);
            throw new RuntimeException("Error");
        });
        
        log.info("   ❌ 异常被包装在 ExecutionException 中");
        try {
            future3.get();
        } catch (ExecutionException e) {
            log.error("   需要从 ExecutionException 中提取真实异常: {}", 
                e.getCause().getMessage());
        }
        
        // 总结
        log.info("\n=== JDK Future 的局限性总结 ===");
        log.info("❌ 1. 没有回调机制，只能阻塞或轮询");
        log.info("❌ 2. 无法组合多个 Future");
        log.info("❌ 3. 异常处理不够优雅");
        log.info("❌ 4. 无法链式调用");
        log.info("❌ 5. 获取结果会阻塞线程\n");
        
        log.info("✅ 解决方案：");
        log.info("   - JDK 8+: 使用 CompletableFuture");
        log.info("   - Netty: 使用 ChannelFuture + Listener");
        
        executor.shutdown();
    }
}

/*
=== 运行结果分析 ===

1. Future 的基本特性：
   - 代表异步计算的结果
   - 提交任务后立即返回 Future
   - 通过 get() 获取结果（会阻塞）

2. 核心方法：
   - get()：阻塞获取结果
   - get(timeout, unit)：带超时的获取
   - isDone()：检查是否完成
   - isCancelled()：检查是否取消
   - cancel()：取消任务

3. 主要问题：
   - 没有回调机制
   - 只能阻塞或轮询
   - 无法优雅地组合
   - 异常处理繁琐

=== 关键知识点 ===

1. Future 是 Java 5 引入的异步编程基础
2. get() 会阻塞线程，要谨慎使用
3. 轮询 isDone() 浪费 CPU 资源
4. cancel() 可以取消任务，但不保证一定成功
5. Future 的局限性促使了 CompletableFuture 的诞生

=== 最佳实践 ===

✅ 在独立线程或线程池中使用 get()
✅ 使用带超时的 get(timeout, unit)
✅ 正确处理 ExecutionException
✅ 考虑使用 CompletableFuture（Java 8+）

❌ 不要在主线程中阻塞调用 get()
❌ 不要频繁轮询 isDone()
❌ 不要忽略异常处理
*/

